package com.rizzo.android.content.processor;

import android.content.*;
import android.database.Cursor;
import android.os.RemoteException;
import android.util.Log;
import com.rizzo.analytics.domain.quota.Quota;
import com.rizzo.analytics.domain.quota.Quotas;
import com.rizzo.android.content.RizzoContent;
import com.rizzo.android.content.http.StateHolder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.Collection;
import java.util.Map;

// TODO should be an interface and add update time to db entries so that we can delete old non existing while syncing
public class QuotaProcessor extends RizzoContentProcessor {

    private ContentProviderClient contentProviderClient;
    private SyncResult syncResult;

    public QuotaProcessor(StateHolder stateHolder, String application, ContentProviderClient contentProviderClient, SyncResult syncResult) {
        super(stateHolder, application);
        this.contentProviderClient = contentProviderClient;
        this.syncResult = syncResult;
    }

    public ContentProviderResult[] process(Map<String, Collection<String>> quotas) {

        ArrayList<ContentProviderOperation> batchOperations = new ArrayList<ContentProviderOperation>();

        for (Map.Entry<String, Collection<String>> userCategoryEntry : quotas.entrySet()) {
            for (String category : userCategoryEntry.getValue()) {
                try {
                    Quotas quotaData = stateHolder.getQuotas(application, category);
                    for (Quota data : quotaData.getQuotas()) {
                        Cursor cursor = contentProviderClient.query(RizzoContent.Quota.CONTENT_URI, RizzoContent.Quota.AVAILABLE_COLUMNS,
                                com.rizzo.android.domain.Quota.APPLICATION_FIELD + " = ? and "
                                        + com.rizzo.android.domain.Quota.METHOD_FIELD + " = ?"
                                        + com.rizzo.android.domain.Quota.USER_FIELD + " = ?", new String[]{application, data.getMethod(), userCategoryEntry.getKey()},
                                null);


                        final ContentValues saveValues = new ContentValues();
                        saveValues.put(RizzoContent.Quota.APPLICATION_FIELD, application);
                        saveValues.put(RizzoContent.Quota.METHOD_FIELD, data.getMethod());
                        // TODO remove the user from the contentprovider!
                        saveValues.put(RizzoContent.Quota.USER_FIELD, userCategoryEntry.getKey());
                        saveValues.put(RizzoContent.Quota.HITS_FIELD, data.getHits());
                        saveValues.put(RizzoContent.Quota.LAST_UPDATED_FIELD, Calendar.getInstance().getTimeInMillis());

                        final ContentValues updateValues = new ContentValues();
                        updateValues.put(RizzoContent.Quota.HITS_FIELD, data.getHits());
                        updateValues.put(RizzoContent.Quota.LAST_UPDATED_FIELD, Calendar.getInstance().getTimeInMillis());

                        final String updateWhere = com.rizzo.android.domain.Quota.APPLICATION_FIELD + " = ? and "
                                + com.rizzo.android.domain.Quota.METHOD_FIELD + " = ?"
                                + com.rizzo.android.domain.Quota.USER_FIELD + " = ?";
                        final String[] updateWhereArgs = {application, data.getMethod(), userCategoryEntry.getKey()};

                        batchOperations.add(saveOrUpdate(cursor, saveValues, updateValues, updateWhere, updateWhereArgs));
                    }
                } catch (RemoteException e) {
                    Log.e("QuotaProcessor", "RemoteException while syncing the quotas for application: " + application
                            + " and category: " + category, e);
                    syncResult.stats.numParseExceptions++;
                } catch (IOException e) {
                    Log.e("QuotaProcessor", "IOException while syncing the quotas for application: " + application
                            + " and category: " + category, e);
                    syncResult.stats.numIoExceptions++;
                }
            }
        }
        try {
            return contentProviderClient.applyBatch(batchOperations);
        } catch (RemoteException e) {
            Log.e("QuotaProcessor", "RemoteException while applying syncing batch for quotas for application: " + application, e);
        } catch (OperationApplicationException e) {
            Log.e("QuotaProcessor", "OperationApplicationException while applying syncing batch for quotas for application: " + application, e);
        }
        return new ContentProviderResult[0];
    }
}
